package com.usian.comment.service.impl;

import com.usian.comment.entity.ApComment;
import com.usian.comment.entity.ApCommentLike;
import com.usian.comment.service.CommentService;
import com.usian.comment.vo.CommentVo;
import com.usian.common.aliyun.GreenTextScan;
import com.usian.common.enums.AppHttpCodeEnum;
import com.usian.common.exception.LeadException;
import com.usian.common.threadlocal.UserThreadLocalUtils;
import com.usian.common.util.BeanHelper;
import com.usian.model.comment.dtos.CommentDto;
import com.usian.model.comment.dtos.CommentLikeDto;
import com.usian.model.comment.dtos.CommentSaveDto;
import com.usian.model.user.dtos.UserInfoDto;
import com.usian.user.client.UserFeign;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Sort;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.data.mongodb.core.query.Update;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;

import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * @author Fay
 * @date 2022/7/20&10:52
 */
@Service
public class CommentServiceImpl implements CommentService {
    /**
     * 保存评论数据
     * @param dto
     */
    @Autowired
    private GreenTextScan greenTextScan;

    @Autowired
    private UserFeign userFeign;

    @Autowired
    private MongoTemplate mongoTemplate;

    @Override
    public void saveComment(CommentSaveDto dto) {
        //对dto进行校验
        if (dto==null){
            throw new LeadException(AppHttpCodeEnum.PARAM_INVALID,"参数为空");
        }
        //获取线程中的userId
        Integer userId = UserThreadLocalUtils.getUserId();
        //==null || ==0 去登录 评论必须登录才能实现
        if (StringUtils.isEmpty(userId)||userId==0){
            throw new LeadException(AppHttpCodeEnum.NEED_LOGIN);
        }
        //调用阿里云反垃圾
        try {
            Map<String, String> map = greenTextScan.greenTextScan(dto.getContent());
            if (!map.get("suggestion").equals("pass")){
                throw new LeadException(AppHttpCodeEnum.TEXT_ILLEGAL);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }

        //远程调用userFeign
        UserInfoDto userInfoDto = userFeign.findUserById(userId);

        if (userInfoDto==null){
            throw new LeadException(AppHttpCodeEnum.NEED_LOGIN,"登录信息有误");
        }

        ApComment apComment = new ApComment();
        apComment.setAuthorId(userInfoDto.getId());
        apComment.setAuthorName(userInfoDto.getName());
        apComment.setEntryId(dto.getArticleId());
        apComment.setContent(dto.getContent());
        apComment.setCreatedTime(new Date());
        apComment.setUpdatedTime(new Date());
        apComment.setImage(userInfoDto.getImage());
        apComment.setLikes(0);
        apComment.setReply(0);
        apComment.setType(0);
        apComment.setFlag(0);
        mongoTemplate.insert(apComment);
    }

    /**
     * 根据文章id查询文章列表
     * @param dto
     * @return
     */
    @Override
    public List<CommentVo> loadComment(CommentDto dto) {
        //对参数进行校验
        if (dto==null){
            throw new LeadException(AppHttpCodeEnum.PARAM_INVALID,"参数不正确");
        }
        //获取用户的id
        Integer userId = UserThreadLocalUtils.getUserId();
        //对文章id进行判断
        if (dto.getArticleId()==null){
            throw new LeadException(AppHttpCodeEnum.PARAM_INVALID,"必须传文章id");
        }
        //entryId 为存储在mongo中的文章id 根据文章id进行查询
        Query query = Query.query(Criteria.where("entryId").is(dto.getArticleId()));
        //设置分页
        PageRequest pageRequest = PageRequest.of(dto.getPage().intValue() - 1, dto.getSize().intValue());
        query.with(pageRequest);
        //如果minlikes不为空 且有点赞 对点赞进行查询
        if (dto.getMinLikes()!=null && dto.getMinLikes()>0){
            query.addCriteria(Criteria.where("likes").lt(dto.getMinLikes()));
        }
        //设置点赞数量降序
        query.with(Sort.by(Sort.Direction.DESC,"likes"));
        //执行查询
        List<ApComment> apCommentList = mongoTemplate.find(query, ApComment.class);
        if (CollectionUtils.isEmpty(apCommentList)){
            throw new LeadException(AppHttpCodeEnum.DATA_NOT_EXIST);
        }
        //数据类型转换
        List<CommentVo> commentVoList = BeanHelper.copyWithCollection(apCommentList, CommentVo.class);
        //如果没有登录就直接返回
        if (userId==null||userId==0){
            return commentVoList;
        }
        //如果是登录需要判断是否点赞
        //对查询的所有id进行收集
        List<String> commentIds = commentVoList.stream().map(CommentVo::getId).collect(Collectors.toList());
        Query query1 = Query.query(Criteria.where("authorId").is(userId).and("commentId").in(commentIds).and("operation").is(0));
        List<ApCommentLike> commentLikes = mongoTemplate.find(query1, ApCommentLike.class);
        if (!StringUtils.isEmpty(commentIds)){
            List<String> commentLikeIds = commentLikes.stream().map(ApCommentLike::getCommentId).collect(Collectors.toList());
            commentVoList.stream().forEach(commentVo -> {
                if (commentLikeIds.contains(commentVo.getId())){
                    commentVo.setOperation(0);
                }
            });
        }
        return commentVoList;
    }

    /**
     * 点赞评论
     * @param dto
     */
    @Override
    public void likeComment(CommentLikeDto dto) {
        //参数校验
        if (dto==null){
            throw new LeadException(AppHttpCodeEnum.PARAM_INVALID,"参数不正确");
        }
        //获取线程中的userId
        Integer userId = UserThreadLocalUtils.getUserId();
        if (userId==null){
            throw new LeadException(AppHttpCodeEnum.NEED_LOGIN,"先去登录");
        }
        //查询评论是否存在
        ApComment apComment = mongoTemplate.findById(dto.getCommentId(), ApComment.class);
        if (apComment==null){
            throw new LeadException(AppHttpCodeEnum.DATA_NOT_EXIST,"评论数据不存在");
        }
        //查询mongo中是否有apcommentList数据
        Query query = Query.query(Criteria.where("commentId").is(dto.getCommentId()).and("authorId").is(userId));
        //获取查询结果
        ApCommentLike apCommentLike = mongoTemplate.findOne(query, ApCommentLike.class);
        //如果like中没有数据 并且 前面传过来的是0 要点赞的数据
        if (apCommentLike==null && dto.getOperation()==0){
            //创建点赞数据
            apCommentLike= new ApCommentLike();
            apCommentLike.setAuthorId(userId);
            apCommentLike.setCommentId(dto.getCommentId());
            apCommentLike.setOperation(dto.getOperation());
            mongoTemplate.insert(apCommentLike);
            //更新评论数据+1
            Query query1 = Query.query(Criteria.where("_id").is(dto.getCommentId()));
            Update update = new Update();
            update.inc("likes");
            mongoTemplate.updateFirst(query1,update,ApComment.class);

        }else if(apCommentLike!=null && apCommentLike.getOperation()!=dto.getOperation() ){
            //如果已经存在 更新点赞的数据 更新点赞的状态
            apCommentLike.setOperation(dto.getOperation());
            mongoTemplate.save(apCommentLike);
            //更新点赞的数量
            Integer opt = dto.getOperation()==0?1:-1;
            if (opt==-1&&apComment.getLikes()<1){
                return;
            }
            Query query1 = Query.query(Criteria.where("_id").is(dto.getCommentId()));
            Update update = new Update();
            update.inc("likes",opt);
            mongoTemplate.updateFirst(query1,update,ApComment.class);
        }
    }
}
